# +----------------------------------------------------------------------
# | ChatWork
# +----------------------------------------------------------------------
# | 这不是一个自由软件,您只能在不用于商业目的的前提下对程序代码进行修改和使用。
# | 任何企业和个人不允许对程序代码以任何形式任何目的再发布,商业使用请获取授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +----------------------------------------------------------------------
import time
from typing import List
from exception import AppException
from common.utils.urls import UrlUtil
from common.utils.times import TimeUtil
from common.enums.agent import AgentEnum
from common.models.users import UserModel
from common.models.agents import AgentRobotModel
from common.models.agents import AgentRobotTeamedModel
from apps.api.schemas.agent.robot import teamed_schema as schema


class RobotTeamedService:
    POWER_VIEW = AgentEnum.POWER_VIEW    # 查看者
    POWER_EDIT = AgentEnum.POWER_EDIT    # 编辑者
    POWER_ADMIN = AgentEnum.POWER_ADMIN  # 管理者
    POWER_OWNED = AgentEnum.POWER_OWNED  # 拥有者

    @classmethod
    async def find_user(cls, params: schema.RobotTeamedSearchIn) -> schema.RobotTeamedUserVo:
        """
        智能体成员查找。

        Args:
            params (schema.RobotTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.RobotTeamedListVo]: 当前用户的权限。

        Author:
            zero
        """
        if not params.keyword:
            raise AppException("请输入需查找的用户编号")

        user = await UserModel.filter(sn=params.keyword).first()
        if user is None:
            raise AppException("搜索不到该用户，请输入正确的用户编号!")

        robot = await AgentRobotModel.filter(code=params.ap_code, is_delete=0).first()
        if robot is None:
            raise AppException("智能体已不存在，请刷新页面再重试吧!")

        if robot.user_id == user.id:
            raise AppException("该用户是本团队管理员，无需重复绑定!")

        member = await AgentRobotTeamedModel.filter(robot_id=robot.id, user_id=user.id).first()
        if member:
            raise AppException("该用户是本团队的成员，无需重复绑定!")

        return schema.RobotTeamedUserVo(
            sn=user.sn,
            nickname=user.nickname,
            avatar=await UrlUtil.to_absolute_url(user.avatar)
        )

    @classmethod
    async def lists(cls, user_id: int, params: schema.RobotTeamedSearchIn) -> List[schema.RobotTeamedListVo]:
        """
        智能体成员列表。

        Args:
            user_id (int): 用户ID
            params (schema.RobotTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.RobotTeamedListVo]: 当前用户的权限。

        Author:
            zero
        """
        robot = await AgentRobotModel.filter(code=params.ap_code, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体被禁用!")

        # 验证权限
        if robot.user_id != user_id:
            await cls.has_permission(robot.code, int(user_id), cls.POWER_VIEW)

        # 查询团队
        lists = await AgentRobotTeamedModel.filter(robot_id=robot.id).all()

        # 提取用户ID
        user_ids = [item.user_id for item in lists if item.user_id]
        users = await UserModel.queryUserDictsById(user_ids)

        _lists = []

        # 智能体拥有者
        owned = await UserModel.filter(id=robot.user_id).first()
        _lists.append(schema.RobotTeamedListVo(
            id=0,
            user_sn=owned.sn,
            user_avatar=await UrlUtil.to_absolute_url(owned.avatar),
            user_nickname=owned.nickname,
            power=cls.POWER_OWNED,
            create_time=TimeUtil.timestamp_to_date(owned.create_time),
            update_time=TimeUtil.timestamp_to_date(owned.update_time)
        ))

        # 智能体协作者
        for item in lists:
            user = users.get(item.user_id, {})
            _lists.append(schema.RobotTeamedListVo(
                id=item.id,
                user_sn=user.get("sn", ""),
                user_avatar=await UrlUtil.to_absolute_url(user.get("avatar", "")),
                user_nickname=user.get("nickname", ""),
                power=item.power,
                create_time=TimeUtil.timestamp_to_date(item.create_time),
                update_time=TimeUtil.timestamp_to_date(item.update_time)
            ))

        return _lists

    @classmethod
    async def add(cls, user_id: int, post: schema.RobotTeamedAddIn) -> None:
        """
        智能体成员添加。

        Args:
            user_id (str): 操作用户ID。
            post (schema.RobotTeamedAddIn): 添加参数。

        Author:
            zero
        """
        # 验智能体
        robot = await AgentRobotModel.filter(code=post.ap_code, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体已禁用!")

        # 验证用户
        user = await UserModel.filter(sn=post.user_sn).first()
        if user is None:
            raise AppException("用户不存在!")
        if user.is_disable:
            raise AppException("用户被限制!")

        # 验证成员
        member = await AgentRobotTeamedModel.filter(robot_id=robot.id, user_id=user.id).first()
        if member or robot.user_id == user.id:
            raise AppException("用户已存在团队中!")

        # 如果不是拥有者 并且 需要添加管理员
        if robot.user_id != user_id and post.power == cls.POWER_ADMIN:
            # 验证添加的权限
            if post.power == cls.POWER_ADMIN:
                raise AppException("抱歉，添加管理员需智能体拥有者操作!")
            # 验证操作的权限
            my = await AgentRobotTeamedModel.filter(robot_id=robot.id, user_id=user_id).first()
            if my is None or my.power != cls.POWER_ADMIN:
                raise AppException("抱歉，您不具备添加成员的操作权限!")

        # 添加到团队中
        await AgentRobotTeamedModel.create(
            robot_id=robot.id,
            user_id=user.id,
            power=post.power,
            create_time=int(time.time()),
            update_time=int(time.time())
        )

    @classmethod
    async def edit(cls, user_id: int, post: schema.RobotTeamedEditIn) -> None:
        """
        智能体成员编辑。

        Args:
            user_id (str): 操作用户ID。
            post (schema.RobotTeamedEditIn): 编辑参数。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentRobotTeamedModel.filter(id=post.id).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验智能体
        robot = await AgentRobotModel.filter(id=teamed.robot_id, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体已禁用!")

        # 如果不是智能体拥有者
        if robot.user_id != user_id:
            # 验证是否是管理员
            my = await AgentRobotTeamedModel.filter(robot_id=robot.id, user_id=user_id).first()
            if my.power != cls.POWER_ADMIN:
                raise AppException("抱歉,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉,您无权限修改管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉,您不能修改自己权限!")

        # 更新权限信息
        await AgentRobotTeamedModel.filter(id=post.id).update(
            power=post.power,
            update_time=int(time.time())
        )

    @classmethod
    async def exits(cls, user_id: int, bot: str) -> None:
        """
        智能体成员退出。

        Args:
            user_id (str): 操作用户ID。
            bot (str): 智能体编号。

        Author:
            zero
        """
        # 验智能体
        robot = await AgentRobotModel.filter(code=bot, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体已禁用!")

        # 验证成员
        teamed = await AgentRobotTeamedModel.filter(user_id=user_id, robot_id=robot.id).first()
        if teamed is None:
            raise AppException("您不是团队成员!")

        # 移除成员
        await AgentRobotTeamedModel.filter(id=teamed.id).delete()

    @classmethod
    async def delete(cls, user_id: int, id_: int) -> None:
        """
        智能体成员删除。

        Args:
            user_id (str): 操作用户ID。
            id_ (int): 成员ID。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentRobotTeamedModel.filter(id=id_).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验智能体
        robot = await AgentRobotModel.filter(id=teamed.robot_id, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体已禁用!")

        # 如果不是智能体拥有者
        if robot.user_id != user_id:
            # 验证是否是管理员
            my = await AgentRobotTeamedModel.filter(robot_id=robot.id, user_id=user_id).first()
            if my.power != cls.POWER_ADMIN:
                raise AppException("抱歉,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉,您无权限删除管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉,您不能自己删除自己!")

        # 删除成员
        await AgentRobotTeamedModel.filter(id=id_).delete()

    @classmethod
    async def has_permission(cls, bot: str, user_id: int, power: int = None) -> int:
        """
        验证用户权限。

        Args:
            bot (str): 智能体编号。
            user_id (str): 用户ID。
            power (str): 最低权限: [1=查看权, 2=编辑权, 3=管理权, 4=所有权]。

        Returns:
            power (int): 当前用户的权限。

        Author:
            zero
        """
        if power is None:
            power = cls.POWER_ADMIN

        robot = await AgentRobotModel.filter(code=bot).first().values("id", "code", "user_id")
        if int(robot["user_id"]) == int(user_id):
            return cls.POWER_OWNED

        member = await AgentRobotTeamedModel.filter(robot_id=robot["id"], user_id=user_id).first()
        if member is None:
            raise AppException("非法操作, 您不是该智能体团队成员!")

        if member.power < power:
            enums = {1: "查看权", 2: "编辑权", 3: "管理权", 4: "拥有权"}
            raise AppException("您无权限操作, 最低所需权限 ["+enums[power]+"]")

        return member.power
